----系统钻石模式游戏流程逻辑
local skynet = require "skynet"
local base = require "base"
local timetool = require "timetool"
local tabletool = require "tabletool"
local timer = require "timer"
local filename = "zsgamelogic.lua"
local filelog = require "filelog"
local dncardtool = require "ssscardtool"
local handcardstool = require "handcardstool"
require "pubenum"
require "sssenum"

local ZsGameLogic = {
    server = nil,
    state_protect = false,
}

function ZsGameLogic.init(service)
    if ZsGameLogic.server == nil then
        ZsGameLogic.server = service
    end
end

function ZsGameLogic.initstate(gameobj, tableobj)
    gameobj.tableobj = tableobj
    gameobj.stateevent[SSSTableState.TABLE_STATE_GAME_START] = ZsGameLogic.game_start
    gameobj.stateevent[SSSTableState.TABLE_STATE_ONE_GAME_START] = ZsGameLogic.one_game_start
    gameobj.stateevent[SSSTableState.TABLE_STATE_DEAL_ALL_CARDS] = ZsGameLogic.deal_all_cards
    gameobj.stateevent[SSSTableState.TABLE_STATE_SORT_CARDS] = ZsGameLogic.sort_cards
    gameobj.stateevent[SSSTableState.TABLE_STATE_ONE_GAME_END] = ZsGameLogic.one_game_end
    gameobj.stateevent[SSSTableState.TABLE_STATE_ONE_GAME_END_AFTER] = ZsGameLogic.one_game_end_after
end

function ZsGameLogic.run(gameobj)
    local f = nil
    local loopcount = 1
    while true do
        if gameobj.tableobj.state == SSSTableState.TABLE_STATE_WAIT_ALL_READY then
            break
        end
        f = gameobj.stateevent[gameobj.tableobj.state]
        if f == nil then
            break
        end
        if loopcount <= 0 then
            ---filelog.sys_error("----------zsgamelogic out of looptimes--------", loopcount, "----table.state----", gameobj.tableobj.state)
            break
        end
        f(gameobj)
        ---filelog.sys_error("-----------在状态切换执行函数执行时，又执行了一次状态切换函数，状态机的状态是：", gameobj.tableobj.state, debug.traceback())
        loopcount = loopcount - 1
    end
end

local function get_curr_round_code(value)
    local code = ""
    if value >= 0 and value < 10 then
        code = code .. "000" ..tostring(value)
    elseif value >= 10 and value < 100 then
        code = code .. "00" .. tostring(value)
    elseif value >= 100 and value <1000 then
        code = code .. "0" .. tostring(value)
    else
        code = code .. tostring(value)
    end
    return code
end


function ZsGameLogic.onegamestart_inittable(gameobj)
	local tableobj = gameobj.tableobj
    local server = ZsGameLogic.server
    local tablelogic = server:get_logicbyname("tablelogic")
    local replaywrite = server:get_logicbyname("replaywrite")
    ----从配置中获取服务费率
    ---tablelogic.set_tip()
	tableobj.one_start_time = timetool.get_time()
    tableobj.one_end_time = 0
	tableobj.banker_seat_index = 0     --当前庄家位置
    tableobj.conf.curr_round_code = get_curr_round_code(tableobj.one_start_time % 10000)
    ----写入回放日志头
    replaywrite.write_replay_head()
    if handcardstool.isopen == true then
        if tableobj.cardspools == nil then
            tableobj.cardspools = {}
            local temp = tabletool.deepcopy(handcardstool.cardspool)
            for i = 1, #temp do
                table.insert(tableobj.cardspools, table.remove(temp, base.get_random(1, #temp)))
            end
        end
    end
	if tableobj.timer_id > 0 then
		timer.cleartimer(tableobj.timer_id)
		tableobj.timer_id = -1
	end
    if tableobj.tablerecords == nil then
        tableobj.tablerecords = {}
    end
    if tableobj.tablerecords.actions == nil then
        tableobj.tablerecords.actions = {}
    end
    local gamename = tablelogic.get_gamename(tableobj)
    local status,cur_rate = skynet.pcall(skynet.call, ".slotmgr", "lua", "get_service_fee_rate", gamename)
    ---filelog.sys_error("------status, cur_rate------", status, cur_rate)
    tableobj.conf.service_fee_rate = cur_rate
    tableobj.is_rematch = false
    tableobj.index_cards_asspools = {}
    ----所有玩家的打枪信息
    tableobj.all_player_shootinfos = {}
    tableobj.shoot_allplayer_infos = {}
    tableobj.shoot_allplayer_rid = 0
    tableobj.next_start_readytime = 0
end

function ZsGameLogic.send_gamestart_notice(gameobj)
    local server = ZsGameLogic.server
	local tableobj = gameobj.tableobj
    local roomtablelogic = server:get_logicbyname("tablelogic")
	local noticemsg = {
		game_info = {
            table_baseinfo = {},
		    table_conf = {},
		    seat_baseinfo = {},
		    seat_playerinfo = {}, 
        }
	}
	roomtablelogic.copy_table_game_info(noticemsg.game_info)
    local allrids = roomtablelogic.getallrids(tableobj)
    server:send_notice_to_players(allrids, "gamestartN", noticemsg, nil, nil)
end

function ZsGameLogic.game_start(gameobj)
    local server = ZsGameLogic.server
    local tableobj = gameobj.tableobj
    local tablelogic = server:get_logicbyname("tablelogic")
    if tableobj.conf.is_train_diamond == 1 then
        local noticemsg = {
            table_index = tableobj.conf.table_index,
            neednum = tableobj.conf.max_player_num,
        }
        tableobj.timer_id = timer.settimer(0.1*100, "train_add_mirror", noticemsg)
    end
    tableobj.state = SSSTableState.TABLE_STATE_WAIT_PLAYER_SITDOWN
end

function ZsGameLogic.one_game_start(gameobj)
    local server = ZsGameLogic.server
    local tableobj = gameobj.tableobj
    local tablelogic = server:get_logicbyname("tablelogic")
    local tablerobothelper = server:get_logicbyname("tablerobothelper")
	ZsGameLogic.onegamestart_inittable(gameobj)
    ----清除旁观列表里的玩家
    tablelogic.kill_all_waiter()
	tableobj.curr_to_num = tableobj.curr_to_num + 1
    ----游戏开始扣除服务费
    ---tablelogic.pay_tip(tableobj)
	--初始化桌位
	local seatlogic = server:get_logicbyname("seatlogic")
	for  _, seat in pairs(tableobj.seats) do
		if not seatlogic.is_empty(seat) and seat.state ~= SSSSeatState.SEAT_STATE_WAIT_NEXT_GAME then
			seatlogic.onegamestart_initseat(seat)
            seat.state = SSSSeatState.SEAT_STATE_PLAYING
		end
	end
	--初始化牌堆
    tablelogic.init_deal_cards()
    ---tablerobothelper.gettablewininfo()
    
    ---写洗牌后手牌情况到牌局回放
    local replaywrite = server:get_logicbyname("replaywrite")
    replaywrite.write_cards_stack()
	--通知client游戏开始
	ZsGameLogic.send_gamestart_notice(gameobj)
	tableobj.state = SSSTableState.TABLE_STATE_ONE_WAIT_GAME_START
    local noticemsg = {
        table_index = tableobj.conf.table_index,
    }
	local timer_id = timer.settimer(2*100, "one_game_start", noticemsg)	
	if tableobj.state ~= SSSTableState.TABLE_STATE_ONE_WAIT_GAME_START then
        if timer_id > 0 then timer.cleartimer(timer_id) end
	else
		tableobj.timer_id = timer_id
	end
end

function ZsGameLogic.deal_all_cards(gameobj)
    filelog.sys_error("-------ZsGameLogic.deal_all_cards-------")
    local server = ZsGameLogic.server
    local tableobj = gameobj.tableobj
    if tableobj.state == SSSTableState.TABLE_STATE_WAIT_DEAL_ALL_CARDS_END then return end
    local roomseatlogic = server:get_logicbyname("seatlogic")
    local tablelogic = server:get_logicbyname("tablelogic")
    for _, seat in ipairs(tableobj.seats) do
        if roomseatlogic.is_ingame(seat) then
            for i=1, 13 do
                -- if handcardstool.isopen == true then
                --     if #seat.cards < 13 then table.insert(seat.cards, table.remove(tableobj.cardspools[seat.index], 1)) end
                -- else
                    if #seat.cards < 13 then 
                        local cards_index = tableobj.index_cards_asspools[seat.rid]
                        if cards_index then
                            if tableobj.deal_cards_temp[cards_index] then
                                table.insert(seat.cards, table.remove(tableobj.deal_cards_temp[cards_index], 1))
                            else
                                table.insert(seat.cards, table.remove(tableobj.deal_cards_temp[seat.index], 1))
                            end
                        else
                            table.insert(seat.cards, table.remove(tableobj.deal_cards_temp[seat.index], 1))
                        end
                    end
                --end
            end
        end             
    end
    
    for _, seat in ipairs(tableobj.seats) do
        if roomseatlogic.is_ingame(seat) then
            roomseatlogic.analysis_special_type(seat)
            roomseatlogic.dealcards(seat)
        end     
    end
    local replaywrite = server:get_logicbyname("replaywrite")
    replaywrite.write_player_handcards()
    ----发送todoN
    local rids = tablelogic.getallrids(tableobj)
    --[[
    //通知玩家操作
    message todoN {
        optional int32 rid = 1;
        optional int32 seat_index = 2;
        optional int32 action_to_time = 3;  //玩家操作到期时间
        optional int32 action_type = 4;
    }
    --]]
    local action_time = tableobj.conf.sort_cards_time
    for index, seat in ipairs(tableobj.seats) do
        if seat.rid ~= 0 and seat.state ~= SSSSeatState.SEAT_STATE_WAIT_NEXT_GAME then
            local noticemsg = {
                rid = seat.rid,
                seat_index = seat.index,
                action_to_time = timetool.get_time() + action_time,
                action_type = SSSActionType.ACTION_SORTCARDS,
            }
            local timernoticemsg = {
                table_index = tableobj.conf.table_index,
                seat_index = seat.index,
                rid = seat.rid,
            }
            seat.timer_id = timer.settimer(action_time * 100, "sort_card_outoftime", timernoticemsg)
            server:send_notice_to_players(rids, "todoN", noticemsg, nil, nil)
            seat.state = SSSSeatState.SEAT_STATE_SORTCARDS
            seat.action_type = SSSActionType.ACTION_SORTCARDS
            seat.action_to_time = action_time + timetool.get_time()
        end
    end
    --设置发牌结束定时器
    tableobj.state = SSSTableState.TABLE_STATE_WAIT_DEAL_ALL_CARDS_END
    local timernoticemsg = {
        table_index = tableobj.conf.table_index,
    }
    
    local timer_id = timer.settimer(action_time * 100, "deal_all_cards_over", timernoticemsg)
    if tableobj.state ~= SSSTableState.TABLE_STATE_WAIT_DEAL_ALL_CARDS_END then
        timer.cleartimer(timer_id)
    else
        tableobj.timer_id = timer_id
    end
end
---所有玩家都理牌完成了
function ZsGameLogic.sort_cards(gameobj)
    filelog.sys_error("-------ZsGameLogic.sort_cards----------")
    local server = ZsGameLogic.server
    local tableobj = gameobj.tableobj
    if tableobj.state == SSSTableState.TABLE_STATE_WAIT_SORT_CARDS then return end
    local roomtablelogic = server:get_logicbyname("tablelogic")
    ---计算所有的输赢水数
    roomtablelogic.balance_water()
    tableobj.state = SSSTableState.TABLE_STATE_WAIT_SORT_CARDS
    local timernoticemsg = {
        table_index = tableobj.conf.table_index,
    }
    local timer_id = timer.settimer(1 * 100, "sort_cards_over", timernoticemsg)
    if tableobj.state ~= SSSTableState.TABLE_STATE_WAIT_SORT_CARDS then
        timer.cleartimer(timer_id)
    else
        tableobj.timer_id = timer_id
    end
end

function ZsGameLogic.one_game_end(gameobj)
    filelog.sys_error("--------ZsGameLogic.one_game_end-------")
    local server = ZsGameLogic.server
    local tableobj = gameobj.tableobj
    if tableobj.state == SSSTableState.TABLE_STATE_WAIT_ONE_GAME_END then return end
    tableobj.one_end_time = timetool.get_time()
    local roomtablelogic = server:get_logicbyname("tablelogic")
    roomtablelogic.balance(tableobj)
    ----发送结算结果
    --[[
        //游戏结算
        //一局游戏结束,推送游戏结果给玩家
        message gamebalanceN {
            optional int32 basescores = 1; // 底分
            optional table_gameinfo game_info = 2;
            repeated player_gameend player_infos = 3; //座位上每个玩家的结算信息
            repeated shoot_playerinfo  shoot_playerinfos = 4;  //牌桌内打枪信息
            repeated shoot_playerinfo  shoot_allplayerinfos = 5; //全垒打的信息
        }
    --]]
    local balancentc = {
        basescores = tableobj.conf.score_diamond,
        game_info = {
            table_baseinfo = {},
		    table_conf = {},
		    seat_baseinfo = {},
		    seat_playerinfo = {},
        },
        player_infos = {},
        shoot_playerinfos = {},
        shoot_allplayerinfos = {},
    }
    roomtablelogic.copy_table_game_info(balancentc.game_info)
    roomtablelogic.copy_gameendinfo(balancentc.player_infos)
    roomtablelogic.copy_shootplayerinfos(balancentc.shoot_playerinfos)
    roomtablelogic.copy_shootallplayerinfos(balancentc.shoot_allplayerinfos)
    local rids = roomtablelogic.getallrids(tableobj)
    server:send_notice_to_players(rids, "gamebalanceN", balancentc, nil, nil)
    filelog.sys_error("--------gamebalanceN---------", balancentc)
    ---有操作,更新心跳时间
    server:update_heart_time()
    local replaywrite = server:get_logicbyname("replaywrite")
    replaywrite.write_balance_info()
    tableobj.state = SSSTableState.TABLE_STATE_WAIT_ONE_GAME_END
    local nowtime = timetool.get_time()
    local delay_time = roomtablelogic.get_movietime()
    local noticemsg = {
        table_index = tableobj.conf.table_index,
    }
    tableobj.next_start_readytime = nowtime + math.floor(delay_time/100)
    filelog.sys_error("------delay_time-----", delay_time, nowtime, tableobj.next_start_readytime)
    local timer_id = timer.settimer(delay_time, "wait_game_end_over", noticemsg)
	if tableobj.state ~= SSSTableState.TABLE_STATE_WAIT_ONE_GAME_END then
		timer.cleartimer(timer_id)
	else
		tableobj.timer_id = timer_id
	end
end

function ZsGameLogic.one_game_end_after(gameobj)
    local server = ZsGameLogic.server
    local tableobj = gameobj.tableobj
    local seatlogic = server:get_logicbyname("seatlogic")
    local tablelogic = server:get_logicbyname("tablelogic")
    local tablerobothelper = server:get_logicbyname("tablerobothelper")
    ----清除旁观列表里的玩家
    tablelogic.kill_all_waiter()
    tablerobothelper.check_robot_diamond()
    local is_table_end = tableobj.table_end_flag
    ----filelog.sys_error("----is_table_end---", is_table_end)
    if is_table_end == true then
        tablelogic.resetdata()
        tableobj.state = SSSTableState.TABLE_STATE_WAIT_PLAYER_SITDOWN
        if tableobj.delete_table_timer_id > 0 then
            timer.cleartimer(tableobj.delete_table_timer_id)
            tableobj.delete_table_timer_id = -1
        end
        if tableobj.delete_table_timer_id == -1 then
			local noticemsg = {
				table_index = tableobj.conf.table_index,
				reason = "tableend",
			}
			tableobj.delete_table_timer_id = timer.settimer(1*100, "delete_table", noticemsg)
		end
        return 
    end
    tablerobothelper.check_robot_num() 
    tablelogic.resetdata()
    tableobj.state = SSSTableState.TABLE_STATE_WAIT_PLAYER_SITDOWN
    local rids = tablelogic.getallrids(tableobj)
    for index, seat in ipairs(tableobj.seats) do
        if seat.rid ~= 0 then
            if not seatlogic.is_empty(seat) then
			    seatlogic.resetstate(seat)
		    end
            local outoftimermsg = {
                table_index = tableobj.conf.table_index,
		        rid = seat.rid,
                seat_index = seat.index,
                is_matching = seat.is_matching,
	        }
            if not tableobj.conf.is_train_diamond or tableobj.conf.is_train_diamond == 0 then
                seat.ready_timer_id = timer.settimer(tableobj.conf.ready_timeout*100, "doready", outoftimermsg)
            elseif tableobj.conf.is_train_diamond == 1 then
                if seat.is_mirror == false then
                    seat.ready_timer_id = timer.settimer(tableobj.conf.ready_timeout*100, "doready", outoftimermsg)
                elseif seat.is_mirror == true then
                    seat.ready_timer_id = timer.settimer(base.get_random(2,3)*100, "mirror_doready", outoftimermsg)
                end
            end
            seat.ready_to_time = timetool.get_time() + tableobj.conf.ready_timeout
	        local doreadyntcmsg = {
		        rid = seat.rid,
		        seat_index = seat.index,
		        ready_to_time = timetool.get_time() + tableobj.conf.ready_timeout,
	        }
	        server:send_notice_to_players(rids, "doreadyN", doreadyntcmsg, nil, nil)
        end
    end
    local notice_robotmsg = {
        table_index = tableobj.conf.table_index,
    }
    tableobj.notice_robot_timer_id = timer.settimer(base.get_random(1,4) * 100, "delay_notice_robot_ready", notice_robotmsg)
    
    if tableobj.state == SSSTableState.TABLE_STATE_WAIT_PLAYER_SITDOWN then
        tableobj.state = SSSTableState.TABLE_STATE_WAIT_ALL_READY
    end
end

return ZsGameLogic